/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../manager/plugin_manager.h"
#include "main_template.h"
#include <iostream>

#include "../UIAttributesCapi/ui_attributes_capi.h"
#include "../CapiDragDragaction/capi_drag_dragaction_test.h"
#include "../CapiDragControlability/capi_drag_controlability_test.h"

#define INVALID_PARAM 401

namespace ArkUICApiDemo {
static ArkUI_NodeHandle rootNode;
static ArkUI_NativeNodeAPI_1 *nodeAPI;
using FunctionCallBack = std::function<void(ArkUI_NativeNodeAPI_1 *nodeAPI, ArkUI_NodeHandle& rootNode)>;
static std::unordered_map<std::string, FunctionCallBack> xComponentToCreateNativeNode_ = {};
static bool hasInit = false;

void Initialize() {
    xComponentToCreateNativeNode_ = {
        // UIAttributesCapi
        {"UIAttributesCapi0231Page", std::bind(&UIAttrsCapi::CreateNativeNodeUIAttributesCapi0231, std::placeholders::_1, std::placeholders::_2)},
        {"UIAttributesCapi0232Page", std::bind(&UIAttrsCapi::CreateNativeNodeUIAttributesCapi0232, std::placeholders::_1, std::placeholders::_2)},
        // CapiDragDragaction
        {"CapiDragDragaction0010", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0010, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0020", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0020, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0030", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0030, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0040", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0040, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0050", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0050, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0070", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0070, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0080", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0080, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0090", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0090, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0100", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0100, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0110", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0110, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0120", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0120, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0130", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0130, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragDragaction0140", std::bind(&CapiDragDragaction::CreateCapiDragDragaction0140, std::placeholders::_1, std::placeholders::_2)},
        // CapiDragControlability
        {"CapiDragControlability0010", std::bind(&CapiDragControlability::CreateCapiDragControlability0010, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0020", std::bind(&CapiDragControlability::CreateCapiDragControlability0020, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0030", std::bind(&CapiDragControlability::CreateCapiDragControlability0030, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0050", std::bind(&CapiDragControlability::CreateCapiDragControlability0050, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0090", std::bind(&CapiDragControlability::CreateCapiDragControlability0090, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0100", std::bind(&CapiDragControlability::CreateCapiDragControlability0100, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0110", std::bind(&CapiDragControlability::CreateCapiDragControlability0110, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0120", std::bind(&CapiDragControlability::CreateCapiDragControlability0120, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0130", std::bind(&CapiDragControlability::CreateCapiDragControlability0130, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0140", std::bind(&CapiDragControlability::CreateCapiDragControlability0140, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0150", std::bind(&CapiDragControlability::CreateCapiDragControlability0150, std::placeholders::_1, std::placeholders::_2)},
        {"CapiDragControlability0160", std::bind(&CapiDragControlability::CreateCapiDragControlability0160, std::placeholders::_1, std::placeholders::_2)},

        // add new native node...
    };
}

void DistributeAndCreateNodeByXComponentId(const std::string& componentId)
{
    if (!hasInit) {
        Initialize();
    }
    auto itor = xComponentToCreateNativeNode_.find(componentId);
    if (itor != xComponentToCreateNativeNode_.end()) {
        itor->second(nodeAPI, rootNode);
    } else {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "DistributeEvent", "can not find xComponentId : %{public}s", componentId.c_str());
    }
    
}

napi_value MainTemplate::NativeCapiMainTest(napi_env env, napi_callback_info info)
{
    // 获取id
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    size_t length = 64;
    size_t strLength = 0;
    char xComponentID[64] = {0};
    napi_get_value_string_utf8(env, args[0], xComponentID, length, &strLength);
    OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
    // 按照XComponentId分发事件，并创建rootNode组件
    std::string xComponentIdStr(xComponentID);
    DistributeAndCreateNodeByXComponentId(xComponentIdStr);
    // 绑定NativeXComponent 和 rootNode
    OH_NativeXComponent_AttachNativeRootNode(PluginManager::GetInstance()->GetNativeXComponent(xComponentIdStr), rootNode);
    napi_value exports;
    napi_create_object(env, &exports);

    return exports;
}
} // namespace ArkUICApiDemo